#include "shaderFractal4d.h"

#include <boost/numeric/ublas/io.hpp>

namespace fractals {
	using namespace boost::numeric::ublas;

	const float WHEEL_STEP_ANGLE=.1f;

	ShaderFractal4d::ShaderFractal4d(const char *filename) 
		: ShaderFractal(filename),
		x(false),
		y(false),
		z(false),
		w(false),
		transform(identity_matrix<float>(4))
	{
		use(shader())
			shader().setUniform("transform", transform);
	}

	void ShaderFractal4d::mouseDown(Button button, int x, int y) {}
	void ShaderFractal4d::mouseMove(int x, int y) {}

	void ShaderFractal4d::keyDown(unsigned char key) {
		if(key == 'x') x=true;
		if(key == 'y') y=true;
		if(key == 'z') z=true;
		if(key == 'w') w=true;
	}

	void ShaderFractal4d::keyUp(unsigned char key) {
		if(key == 'x') x=false;
		if(key == 'y') y=false;
		if(key == 'z') z=false;
		if(key == 'w') w=false;
	}

	void ShaderFractal4d::mouseWheelDown() {
		planeRotate(-WHEEL_STEP_ANGLE);
	}

	void ShaderFractal4d::mouseWheelUp() {
		planeRotate(WHEEL_STEP_ANGLE);
	}

	void ShaderFractal4d::planeRotate(float angle) {
		mat4 t=identity_matrix<float>(4);

		mat4::size_type index1, index2;

		if(x && y) 
			index1=2, index2=3;
		else if(x && z)
			index1=1, index2=3;
		else if(x && w)
			index1=1, index2=2;
		else if(y && z)
			index1=0, index2=3;
		else if(y && w)
			index1=0, index2=2;
		else if(z && w)
			index1=0, index2=1;
		else
			return;

		float c=cos(angle), s=sin(angle);

		t(index1, index1)=c;
		t(index1, index2)=-s;
		t(index2, index1)=s;
		t(index2, index2)=c;

		transform = prod(t, transform);

		use(shader())
			shader().setUniform("transform", transform);
	}
}